package com.bigshen.springcloud.demo.springcloudgateway8080;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

/**
 * 扩展路由数据的持久化
 * 根据Redis实现
 */
@Component
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {

    private static final String GATEWAY_ROUTE_KEY = "gateway_dynamic_route";

    @Autowired
    RedisTemplate<String, String> redisTemplate;

    /**
     * 获取路由信息
     * @return
     */
    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        List<RouteDefinition> routeDefinitionList = new ArrayList<>();
        redisTemplate.opsForHash().values(GATEWAY_ROUTE_KEY).stream().forEach(route -> {
            routeDefinitionList.add(JSON.parseObject(route.toString(), RouteDefinition.class));
        });
        return Flux.fromIterable(routeDefinitionList);
    }

    /**
     * 保存路由信息
     * @param route
     * @return
     */
    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return route.flatMap(routeDefinition -> {
            redisTemplate.opsForHash().put(GATEWAY_ROUTE_KEY, routeDefinition.getId(), JSON.toJSONString(routeDefinition));
            return Mono.empty();
        });
    }

    /**
     * 删除路由信息
     * @param routeId
     * @return
     */
    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return routeId.flatMap(id -> {
            if (redisTemplate.opsForHash().hasKey(GATEWAY_ROUTE_KEY, id)) {
                redisTemplate.opsForHash().delete(GATEWAY_ROUTE_KEY, id);
                return Mono.empty();
            }
            return Mono.defer(() -> Mono.error(new Exception("RouteDefinition not found: " + routeId)));
        });
    }
}
